#pragma once
#include "Log.hpp"
#include <mutex>
#include <thread>
#include <condition_variable>
#include <vector>
#include <queue>
#include <atomic>
#include <functional>

namespace Mythreadpool
{
    int defaultnum = 5;
    using thread_t = std::shared_ptr<std::thread>;
    template <class T>
    class threadpool
    {
        // void defaultfun()
        // {
        //     while (true)
        //     {
        //         std::cout << "我是一个测试函数" << std::endl;
        //         sleep(1);
        //     }
        // }
        void HandlerTask()
        {
            // 如果在运行
            T t;
            while (_isrunning.load())
            {
                {
                    std::unique_lock _lck(mtx);
                    while (IsEmpty() && _isrunning.load())
                    {
                        _wait_num++;
                        cv.wait(_lck, [this]
                                { return !(threadpool::IsEmpty()); });
                        _wait_num--;
                    }
                    if (IsEmpty() && !_isrunning.load())
                        break; // 如果队列为空 且 线程池停止了
                    t = _taskq.front();
                    _taskq.pop();
                }
                t();
            }
        }
        bool IsEmpty() { return _taskq.empty(); }
        threadpool(int num = defaultnum) : _num(num), _isrunning(false), _wait_num(0)
        {
            threads.resize(_num);
            _isrunning = true;
            for (int i = 0; i < _num; i++)
            {
                std::cout << "启动线程: " << i << std::endl;
                threads[i] = std::make_shared<std::thread>(&threadpool::HandlerTask, this);
                // threads[i] = std::make_shared<std::thread>([this] {threadpool::defaultfun();});
            }
        }

    public:

        void Equeue(T data)
        {
            if (!_isrunning.load())
                return;
            {
                std::unique_lock _lck(mtx);
                if (_wait_num > 0)
                    cv.notify_one();
                _taskq.push(data);
            }
        }
        void Wait()
        {
            cv.notify_all();
            _isrunning = false;
            for (auto thread_ptr : threads)
            {
                thread_ptr->join();
                std::cout << "回收线程成功" << std::endl;
            }
        }
        ~threadpool()
        {
        }
        static std::mutex mmtx;
        static threadpool<T>* _instance;
        static threadpool<T>* GetInstance()
        {
            if (_instance == nullptr)
            {
                std::unique_lock _lck(mmtx);
                if (_instance == nullptr) 
                {
                    _instance = new threadpool();
                }
            }
            return _instance;
        }
    private:
        int _num;
        std::vector<thread_t> threads;
        std::queue<T> _taskq;
        std::mutex mtx;
        std::condition_variable cv;
        std::atomic<bool> _isrunning;
        int _wait_num;
    };

    template<class T>
    threadpool<T>* threadpool<T>::_instance = nullptr;

    template<class T>
    std::mutex threadpool<T>::mmtx;
}